<template>
  <el-card>
    <template v-slot:header>
      <el-button type="primary" icon="el-icon-plus" @click="showAdd"
        v-if="$hasBP('btn.Trademark.add')">添加</el-button>
    </template>
    <template>
      <el-table
        border
        v-loading="loading"
        style="width: 100%"
        :data="trademarks"
        row-key="id">
        <!-- 序号 -->
        <el-table-column
          type="index"
          align="center"
          label="序号"
          width="80">
        </el-table-column>
        <!-- <el-table-column
          label="序号">
          <template v-slot="{$index}">
            {{$index + 1}}
          </template>
        </el-table-column> -->

        <el-table-column
          prop="tmName"
          label="品牌名称">
        </el-table-column>

        <el-table-column
          label="品牌LOGO">
          <template v-slot="{row, $index}">
            <el-image :src="row.logoUrl" alt="logo" style="width: 100px;height: 80px;" />
          </template>
        </el-table-column>

        <!-- <slot :row="当前行数据对象" :$index="当前下标"/> -->


         <el-table-column
          label="操作">
          <template v-slot="{row}">
            <!-- 
          <HintButton/>
          <hint-button/>
          -->
            <hint-button v-if="$hasBP('btn.Trademark.update')" title="修改" type="warning" size="small" icon="el-icon-edit" @click="showUpdate(row)"></hint-button>
            <hint-button v-if="$hasBP('btn.Trademark.remove')" title="删除" type="danger" size="small" icon="el-icon-delete" @click="remove(row)"></hint-button>
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        style="margin-top: 20px; text-align: center;"
        :current-page="page"
        :page-sizes="[5, 10, 15]"
        :page-size="pageSize"
        :total="total"
        layout="prev, pager, next, jumper, ->, sizes, total"
        >
      </el-pagination>

      <el-dialog :title="`${form.id ? '修改' : '添加'}品牌`" :visible.sync="dialogFormVisible">
        <el-form ref="tmForm" :rules="rules" :model="form" label-width="20%" style="width: 80%">

          <el-form-item label="品牌名称" prop="tmName">
            <el-input v-model="form.tmName" placeholder="请输入品牌名称"></el-input>
          </el-form-item>

          <el-form-item label="品牌LOGO" prop="logoUrl">
            <!-- 
              action: 指定处理上传请求的url  ==> 不能直接指定后台接口url(跨域了) => 指定带代理路径的path
              :show-file-list="false"  显示单张图片
              :on-success: 指定上传成功的回调  ==> 得到上传返回的图上rul
              :before-upload: 指定上传请求前的回调 ==> 限定图片的大小(50KB)或类型(JPG/PNG)
            -->
            <el-upload
              class="avatar-uploader"
              :action="$BASE_API +'/admin/product/fileUpload'"
              :show-file-list="false"
              :on-success="handleAvatarSuccess"
              :before-upload="beforeAvatarUpload">
              <img v-if="form.logoUrl" :src="form.logoUrl" class="avatar">
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
              <div class="el-upload__tip" slot="tip">只能上传jpg/png文件，且不超过50kb</div>
            </el-upload>
          </el-form-item>

        </el-form>

        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogFormVisible = false">取 消</el-button>
          <el-button type="primary" @click="addOrUpdate" :loading="saveLoading">确 定</el-button>
        </div>
      </el-dialog>
    </template>
  </el-card>
</template>

<script>
export default {
  name: 'TrademarkList',
   data() {

    return {
      trademarks:  [], // 当前页列表
      page: 1, // 当前页码
      pageSize: 5, // 每页数量
      total: 0, // 总数量
      loading: false, // 是否正在请求加载中

      dialogFormVisible: false, // 对话框是否显示
      form: { // 用于收集表单的form对象
        tmName: '',
        logoUrl: '',
      },

      rules: {
          tmName: [
            /* 声明式校验: 利用内置的校验规则进行校验, 不需要自己进行判断 */
            { required: true, message: '请输入品牌名称', trigger: 'change' },
            /* 自定义校验:  通过校验器配置指定校验函数来亲自判断*/
            // { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }
            { validator: this.validateTmName, trigger: 'blur' }
            
          ],
          logoUrl: [
            { required: true, message: '请指定LOGO图片', trigger: 'change' }
          ]
      },
      saveLoading: false, // 是否显示保存的loading
    }
   },

  async mounted () {
    // 初始获取第一页列表显示
    this.getList()
  },

  watch: {
    dialogFormVisible (value) {
      // 必须得显示之后处理
      if (value) {
         this.$nextTick(() => {
          this.$refs.tmForm.clearValidate()
        })
      }

      // 必须得隐藏之前处理  ==> 打开时可能还是会显示错误信息
      // if (!value) {
      //   this.$refs.tmForm.clearValidate()
      // }
    }
  },

  methods: {

    /* 
    删除指定品牌
    */
    remove(trademark) {
      // 显示确定框
      this.$confirm(`确定删除${trademark.tmName}吗?`, '提示', {
          // confirmButtonText: '确定',
          // cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => { // 点击确定的回调
          // 发删除品牌的请求
          await this.$API.trademark.remove(trademark.id)
          this.$message.success('删除品牌成功!')
          // 重新获取列表显示
          // 如果当前页只有一条数据了 ==> 显示上一页
          if (this.trademarks.length===1) {
            this.page--
          }
          this.getList()
        }
        /* ,
        
          (error) => { // 点击取消的回调
            this.$message({
              type: 'info',
              message: '已取消删除'
            })   
          }
         */
        ).catch((error) => { // 点击取消的回调
          // console.log(error)
          if (error==='cancel') { // 只有点击取消才提示
            this.$message({
              type: 'info',
              message: '已取消删除'
            })   
          }
             
        })
    },

    /* 
    添加或更新 
    */
    addOrUpdate () {
      // 对所有表单项进行校验
      this.$refs['tmForm'].validate(async (valid) => {
        // 校验通过
        if (valid) {
          try {
            // 发送添加/更新的请求
            const {form} = this
            this.saveLoading = true  // 请求前显示loading
            await this.$API.trademark[form.id ? 'update' : 'add'](form)
            // if (form.id) {
            //   this.$API.trademark.update(form)
            // } else {
            //   this.$API.trademark.add(form)
            // }
            // 提示成功
            this.$message({
              type: 'success',
              message: `${form.id ? '更新' : '添加'}成功`
            })
            // 关闭dialog
            this.dialogFormVisible = false
            // 重新获取分页列表: 如果是更新是当前页, 如果是添加是第一页
            if (!form.id) {
              this.page = 1
            }
            this.getList()
          } finally { // 异步请求成功或失败最终都会执行
            this.saveLoading = false // 隐藏loading
          }
          
        } /* else {
          alert('校验失败')
        } */
      })
    },

    /* 
    对品牌名称进行自定义校验的函数
    value: 品牌名称值
    callback: 用来指定校验是否通过的函数(由我们调用)
      callback(): 代表校验通过
      callback(error/msg): 代表校验不通过, 并指定提示信息
    */
    validateTmName (rule, value, callback) {
      if (value.length<2 || value.length>10) {
        callback('长度在 2 到 10 个字符') // 代表校验不通过, 并指定提示信息
      } else {
        callback() // 代表校验通过
      }
    },

    /* 
    显示修改界面
    */
    showUpdate (trademark) {  // {tmName: 'a', logoUrl: 'url'}
      // 指定表单数据
      // this.form = trademark   // 问题: 2个引用变量指向同一个对象导致
      /* 
      问题2: 点击修改品牌, 指定新的品牌名称后, 不能取消
	    原因: 列表中的当前品牌的名称已经修改了
      解决: 对要修改的trademark做浅拷贝   ==> 不需要深拷贝, 因为对象中的属性是基本类型的string
      */
      this.form = {...trademark}

      // 显示dialog
      this.dialogFormVisible = true

      // 必须等到dialog显示之后才能处理
      // this.$nextTick(() => {
      //   this.$refs.tmForm.clearValidate()
      // })
    },

    /* 
    显示添加界面
    */
    showAdd () {
      /* 
      问题1: 点击修改后再点击添加显示修改界面
      原因: 点击添加时, 修改时指定form数据还在
      解决: 点击添加时先清除form数据
      */
      this.form = {
        tmName: '',
        logoUrl: '',
      }
      // 显示dialog
      this.dialogFormVisible = true  // 更新数据后, 并不会直接同步更新界面, 而是最后异步更新界面

      /* 
      问题2: 显示错误信息后关闭再打dialog, 错误信息还在
      原因: dialog隐藏时, 对应的元素还存在, 显示时直接复用(包含错误信息的元素也还在)  且没有清除错误信息
      解决: 关闭或打开时,清除错误信息  ==> 必须在界面显示后才处理 ==> 使用$nextTick()
      */
      // 必须等到dialog显示之后才能处理
      // this.$nextTick(() => {
      //   this.$refs.tmForm.clearValidate()
      // })
     
    },

    /* 
    上传成功的回调  ==> 得到上传返回的图上rul
    */
    handleAvatarSuccess(result) {
      // 保存上传成功的图片url
      this.form.logoUrl = result.data // 并不会触发重新校验
      /* 
       问题1: 上传图片完成后, 图片的校验错误信息没有清除
      原因: 上传图片完成更新logoUrl数据后, 没有自动触发重新校验
      解决: 我们去对图片重新校验或直接清除错误信息
      */
      // this.$refs.tmForm.validateField('logoUrl')
      this.$refs.tmForm.clearValidate('logoUrl')
    },

    /* 
    上传请求前的回调 ==> 限定图片的大小(50KB)或类型(JPG/PNG)
    函数返回true代表提交请求, 返回false代表不提交请求
    */
    beforeAvatarUpload(file) {
      const isJPGOrPNG = file.type === 'image/jpeg' || file.type === 'image/png'
      const isLt50KB = file.size / 1024 <= 50

      // 如果超过大小限制, 提示
      if (!isLt50KB) {
        this.$message.error('上传头像图片大小不能超过 50KB!')
      }

      // 如果类型不满足, 提示
      if (!isJPGOrPNG) {
        this.$message.error('上传头像图片只能是 JPG/PNG 格式!')
      }

      // 只有类型和大小都满足时才返回true
      return isJPGOrPNG && isLt50KB
    },

    /* 
    处理每页数量发生改变的监听
    */
    handleSizeChange (pageSize) {
      // 更新每页数量
      this.pageSize = pageSize
      // 更新当前页码为1
      this.page = 1
      // 请求获取当前页码的列表数据
      this.getList()
    },

    /* 
    处理当前页码发生改变的监听
    currentPage: 当前最新页码
    */
    handleCurrentChange (currentPage) {
      // 更新page
      this.page = currentPage
      // 请求获取当前页码的列表数据
      this.getList()
    },

    async getList () {
      this.loading = true // 显示loading
      // 请求获取数据
      const result = await this.$API.trademark.getList(this.page, this.pageSize)
      this.loading = false // 隐藏loading
      // 读取数据更新
      const {records, total} = result.data
      this.trademarks = records
      this.total = total
    }
  }
}
</script>

<style>
  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
</style>
<style lang="scss" scoped>

</style>
